from asyncio import subprocess
import random
import requests
import json
import csv
import time
import logging
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import urllib.parse
import os

# 设置日志
logging.basicConfig(
    filename="zhongyaocaixiangxi.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
)

# 配置请求头
headers = {
    "Accept": "application/json, text/plain, */*",
    "Accept-Encoding": "gzip, deflate",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Connection": "keep-alive",
    "Content-Type": "application/json;charset=UTF-8",
    "DNT": "1",
    "Host": "www.tcmip.cn:18124",
    "Origin": "http://www.tcmip.cn",
    "Referer": "http://www.tcmip.cn/",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
}

# 设置请求重试策略
retry_strategy = Retry(
    total=5,
    backoff_factor=1,
    status_forcelist=[500, 502, 503, 504],
)

adapter = HTTPAdapter(max_retries=retry_strategy)

# 创建请求会话
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)

# 目标 CSV 文件
csv_filename = "zhongyaocaixiangxi.csv"

# 初始化 CSV（如果文件不存在，添加表头）
if not os.path.exists(csv_filename):
    with open(csv_filename, mode="w", encoding="utf-8", newline="") as f:
        writer = csv.writer(f)
        writer.writerow(
            [
                "方剂名称",
                "剂型",
                "症状体征/临床表现",
                "处方来源",
                "组成原文",
                "方剂功能主治原文注释",
                "相关中药材列表",
                "具有相似组方中药材的中医古籍方剂列表",
                "具有相似组方化学成分谱的中医古籍方剂列表"
                "具有相似组方中药材的中成药列表",
                "具有相似组方靶标谱的中成药列表",
            ]
        )


# 获取 API 数据
def get_data(interface_url: str):
    try:
        response = session.get(interface_url, headers=headers, timeout=10)
        response.raise_for_status()  # 遇到 HTTP 错误状态码则抛出异常
        return response.json().get("data", [])
    except Exception as e:
        logging.error(f"请求失败: {e}")
        return []


time_g_begin = time.time()

# 读取药材列表
with open("zhongyaocai.csv", mode="r", encoding="utf-8", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        time_begin = time.time()

        name = row[0]
        url = f"http://www.tcmip.cn:18124/home/detail/?id={urllib.parse.quote(name)}&type=traditional_chinese_medicine_formula&language=cn"

        # 获取数据
        data = get_data(url)

        # 解析基本信息
        herb_info = {
            "方剂名称": name,
            "剂型": "",
            "症状体征/临床表现": "",
            "处方来源": "",
            "组成原文": "",
            "方剂功能主治原文注释": "",
            "相关中药材列表": "",
            "具有相似组方中药材的中医古籍方剂列表": "",
            "具有相似组方中药材的中医古籍方剂列表相似值": "",
            "具有相似组方化学成分谱的中医古籍方剂列表": "",
            "具有相似组方化学成分谱的中医古籍方剂列表相似值": "",
            "具有相似组方中药材的中成药列表": "",
            "具有相似组方中药材的中成药列表相似值": "",
            "具有相似组方化学成分谱的中成药列表": "",
            "具有相似组方化学成分谱的中成药列表相似值": "",
        }

        chinese_patent_drugs = []  # 存放相关中成药数据

        for section in data:
            if section["key"] == "基本信息":
                for item in section["value"]:
                    if item["key"] in herb_info:
                        herb_info[item["key"]] = item["value"]

            elif section["key"] == "相关信息表":
                linkMed: list[str] = []
                for item in section["value"][0]["value"]:
                    linkMed.append(item["中药材名称"][0])
                # print(linkMed)
                herb_info["相关中药材列表"] = ",".join(linkMed)

            elif section["key"] == "相似中医古籍方剂":
                linkedFangJi: list[str] = []
                linkedFangJiNumber: list[str] = []
                if len(section["value"]) > 0:
                    for item in section["value"][0]["value"]:
                        linkedFangJi.append(item[0]["value"])
                        linkedFangJiNumber.append(item[1]["value"])
                    herb_info["具有相似组方中药材的中医古籍方剂列表"] = ",".join(
                        linkedFangJi
                    )
                    herb_info["具有相似组方中药材的中医古籍方剂列表相似值"] = ",".join(
                        linkedFangJiNumber
                    )

                linkedHuaxue: list[str] = []
                linkedHuaxueNumber: list[str] = []
                if len(section["value"]) > 1:
                    for item in section["value"][1]["value"]:
                        linkedHuaxue.append(item[0]["value"])
                        linkedHuaxueNumber.append(item[1]["value"])
                    # print(linkedFangJi, linkedHuaxue)
                    herb_info["具有相似组方化学成分谱的中医古籍方剂列表"] = ",".join(
                        linkedHuaxue
                    )
                    herb_info["具有相似组方化学成分谱的中医古籍方剂列表相似值"] = (
                        ",".join(linkedHuaxueNumber)
                    )

            elif section["key"] == "相似中成药":
                likeHerbList: list[str] = []
                likeHerbNumberList: list[str] = []
                if len(section["value"]) > 0:
                    for item in section["value"][0]["value"]:
                        likeHerbList.append(item[0]["value"])
                        likeHerbNumberList.append(item[1]["value"])
                    herb_info["具有相似组方中药材的中成药列表"] = ",".join(likeHerbList)
                    herb_info["具有相似组方中药材的中成药列表相似值"] = ",".join(
                        likeHerbNumberList
                    )
                likeChemistryList: list[str] = []
                likeChemistryNumberList: list[str] = []
                if len(section["value"]) > 1:
                    for item in section["value"][1]["value"]:
                        likeChemistryList.append(item[0]["value"])
                        likeChemistryNumberList.append(item[1]["value"])
                    herb_info["具有相似组方化学成分谱的中成药列表"] = ",".join(
                        likeChemistryList
                    )
                    herb_info["具有相似组方化学成分谱的中成药列表相似值"] = ",".join(
                        likeChemistryNumberList
                    )
                # print(likeHerbList, likeChemistryList)

        # 将提取的数据写入到 CSV 文件中
        with open(csv_filename, mode="a", encoding="utf-8", newline="") as f:
            writer = csv.writer(f)
            writer.writerow(
                [
                    herb_info["方剂名称"],
                    herb_info["剂型"],
                    herb_info["症状体征/临床表现"],
                    herb_info["处方来源"],
                    herb_info["组成原文"],
                    herb_info["方剂功能主治原文注释"],
                    herb_info["相关中药材列表"],
                    herb_info["具有相似组方中药材的中医古籍方剂列表"],
                    herb_info["具有相似组方中药材的中医古籍方剂列表相似值"],
                    herb_info["具有相似组方化学成分谱的中医古籍方剂列表"],
                    herb_info["具有相似组方化学成分谱的中医古籍方剂列表相似值"],
                    herb_info["具有相似组方中药材的中成药列表"],
                    herb_info["具有相似组方中药材的中成药列表相似值"],
                    herb_info["具有相似组方化学成分谱的中成药列表"],
                    herb_info["具有相似组方化学成分谱的中成药列表相似值"],
                ]
            )

        logging.info(f"已写入: {row[0]}")
        logging.info(f"耗时: {round(time.time() - time_begin):.2f}")
        time.sleep(random.uniform(10, 15))  # 避免触发反爬机制

logging.info("所有数据请求完成！")
try:
    subprocess.run(["pm2", "stop", "1"], check=True)
    logging.info(f"总耗时: {round((time.time()-time_g_begin)/60,3)} min")
    logging.info("pm2 进程 1 已停止。")
except subprocess.CalledProcessError as e:
    logging.error(f"停止 pm2 进程时出错：{e}")
